export default async function fetchJson<JSON = unknown>(
    input: RequestInfo,
    init?: RequestInit
  ): Promise<JSON> {
    const response = await fetch(input, init)
  
    // if the server replies, there's always some data in json
    // if there's a network error, it will throw at the previous line
    const data = await response.json()
  
    // response.ok is true when res.status is 2xx
    // https://developer.mozilla.org/en-US/docs/Web/API/Response/ok
    if (response.ok) {
      return data
    }
  
    throw new FetchError({
      message: response.statusText,
      response,
      data,
    })
  }
  
  export class FetchError extends Error {
    response: Response
    data: {
      message: string
    }
    constructor({
      message,
      response,
      data,
    }: {
      message: string
      response: Response
      data: {
        message: string
      }
    }) {
      // Pass remaining arguments (including vendor specific ones) to parent constructor
      super(message)
  
      // Maintains proper stack trace for where our error was thrown (only available on V8)
      if (Error.captureStackTrace) {
        Error.captureStackTrace(this, FetchError)
      }
  
      this.name = 'FetchError'
      this.response = response
      this.data = data ?? { message: message }
    }
  }
  